import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { MusicList } from './schemas/musicList.schemas';
import { Model, Types } from 'mongoose';
import { PutObjectResult } from 'ali-oss';
import { GetListDto } from 'src/music/dto/music.dto';
import { CreateRoomDto } from 'src/room/dto/room.dto';
import { Room } from './schemas/room.schemas';
@Injectable()
export class MongoService {
  constructor(
    @InjectModel(MusicList.name) private musicListDB: Model<MusicList>,
    @InjectModel(Room.name) private roomDB: Model<Room>,
  ) {}
  async addMusic(data: PutObjectResult) {
    const newMusic = new this.musicListDB({
      name: data.name,
      md5: data.res.headers['content-md5'],
      url: data.url,
      create_date: new Date().toISOString(),
    });
    await newMusic.save();
  }
  async getList(query: GetListDto) {
    const data = await this.musicListDB
      .find()
      .skip(query.skip)
      .limit(query.limit)
      .exec();
    const total = await this.musicListDB.countDocuments();

    return {
      music: data,
      current: query.skip + 1,
      limit: query.limit,
      total,
    };
  }
  async search(keywords: string) {
    const regex = new RegExp(keywords, 'i');
    return await this.musicListDB
      .find({
        $or: [{ name: regex }],
      })
      .exec();
  }
  async createRoom(data: CreateRoomDto) {
    const newRoom = new this.roomDB(data);
    return newRoom.save();
  }
  async roomExist(data: CreateRoomDto | { _id: string }) {
    return await this.roomDB.exists(data);
  }
  async joinRoom(data: {
    room_id: string;
    random: string;
    user_name: string;
    socket_id: string;
  }) {
    //获取房间所有用户
    const userClients = await this.roomDB.findOne(
      {
        _id: new Types.ObjectId(data.room_id),
      },
      { _id: 0, paylist: 0 },
    );
    //获取房间里是否有这个id
    const userIsExist = userClients.clients.find(
      (item) => item.random === data.random,
    );
    if (userIsExist) {
      //踢出
      await this.roomDB.updateMany(
        { _id: data.room_id },
        { $pull: { clients: { random: data.random } } },
      );
    }
    //将新用户添加进去
    const newUser = await this.roomDB.updateOne<Room>(
      { _id: data.room_id },
      {
        $push: {
          clients: {
            random: data.random,
            user_name: data.user_name,
            socket_id: data.socket_id,
            host: Boolean(userClients.clients.length),
          },
        },
      },
    );

    return {
      res: userIsExist,
      exist: Boolean(userIsExist),
    };
  }
  async getUsers(room_id: string) {
    return await this.roomDB.findOne({ _id: room_id }, { clients: 1 }).exec();
  }
  async exitRoom(room_id: string, user: { random: string; user_name: string }) {
    const res = await this.roomDB.updateOne(
      { _id: room_id },
      {
        $pull: {
          clients: { user_name: user.user_name, random: user.random },
        },
      },
    );
    return res;
  }
  async getMusic(md5: string) {
    return await this.musicListDB.findOne({ md5 }).exec();
  }
  async addPayList(
    room_id: string,
    music: Partial<MusicList> & { create_name: string; create_random: string },
  ) {
    //如果发现播放列表已经存在此歌曲
    await this.roomDB
      .updateMany(
        { _id: room_id },
        {
          $pull: { paylist: { md5: music.md5 } },
        },
      )
      .exec();
    await this.roomDB.updateMany(
      { _id: room_id },
      {
        $push: { paylist: { $each: [music], $position: 0 } },
      },
    );
  }
  async getPayList(room_id: string) {
    return await this.roomDB.findOne({ _id: room_id }, { paylist: 1 });
  }
  /**
   * 查看房间里是否有这个用户
   */
  existUser(room_id: string) {}

  /**
   * 设置房间内成员的加载状态
   */
  setStatus(
    data: {
      room_id: string;
      random: string;
      user_name: string;
    },
    status: string,
  ) {
    return this.roomDB.updateOne(
      {
        _id: new Types.ObjectId(data.room_id),
        clients: {
          $elemMatch: { random: data.random, user_name: data.user_name },
        },
      },
      { $set: { 'clients.$.status': status } },
    );
  }
  /**
   * 获取房间里可以播放的用户
   */
  async getCanplayUser(room_id: string) {
    const users = await this.getUsers(room_id);
    return users.clients.filter((item) => item.status === 'play').length;
  }

  /**
   * 将房间里的所有成员的状态
   */
  async setAllStatus(room_id: string, status: string) {
    return this.roomDB.updateOne(
      { _id: room_id },
      { $set: { 'clients.$[].status': status } },
    );
  }

  /**
   * 获取房间里指定状态的成员
   */
  async getAllStatus(room_id: string, status: string) {
    const users = await this.roomDB.findOne({ _id: room_id }, { clients: 1 });
    return users.clients.filter((item) => item.status === status);
  }
  /**
   * 删除播放完的歌曲
   */
  async delCurrent(room_id: string) {
    return await this.roomDB.updateOne(
      { _id: room_id },
      { $pop: { paylist: -1 } },
    );
  }

  /**
   * 获取播放列表里第1个
   */
  async getFirstPaylist(room_id: string) {
    return await this.roomDB.findOne(
      { _id: new Types.ObjectId(room_id) },
      {
        paylist: 1,
      },
    );
  }
  /**
   * 获取房间信息
   */
  async getRoomInfo(room_id: string) {
    return await this.roomDB.findOne({ _id: room_id }).exec();
  }
}
